//
//  HMCoreDataManager.m
//  02-手动搭建CoreDataStack
//
//  Created by Shenzhen_iOS_07 on 17/1/7.
//  Copyright © 2017年 Shenzhen_iOS_07. All rights reserved.
//

#import "HMCoreDataManager.h"

@interface HMCoreDataManager ()

#pragma amrk - iOS9
//管理对象上下文:负责管理模型对象
@property(nonatomic,strong)NSManagedObjectContext *managedObjectContext1;

//存储调度器:负责调度存储器
@property(nonatomic,strong)NSPersistentStoreCoordinator *persistentStoreCoordinator;

//对象模型(相当于model文件:相当于数据库):负责管理模型对象(相当于model文件中的实体Person:相当于数据库中的表格table)
@property(nonatomic,strong)NSManagedObjectModel *managedObjectModel;

@end



@implementation HMCoreDataManager

+ (HMCoreDataManager*)shareInstance
{
    static HMCoreDataManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[HMCoreDataManager alloc] init];
    });
    return manager;
}

- (NSManagedObjectContext *)managedObjectContext
{
    //判断用户当前的系统版本
    if ([[UIDevice currentDevice].systemVersion floatValue] >= 10.0)//iOS10之后的系统
    {
        return self.persistentContainer.viewContext;
    }
    else//iOS10之前的系统
    {
        //返回的是iOS9的管理对象上下文
        return self.managedObjectContext1;
    }
    
}

#pragma mark -iOS10 CoreData Stack
//懒加载
- (NSPersistentContainer *)persistentContainer
{
    if (_persistentContainer != nil) {
        return _persistentContainer;
    }
    
    NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
    
    //1.创建NSPersistentContainer  第一个参数:数据库文件的名字  第二个参数:管理对象的模型
    _persistentContainer = [[NSPersistentContainer alloc] initWithName:@"sql.db" managedObjectModel:model];
    
    //2.加载存储器(必须要调用,NSPersistentContainer只需要调用加载存储器则会自动帮助我们生成对应的存储调度器和管理对象上下文)
    [_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription * description, NSError * error) {
        NSLog(@"%@",description);
        NSLog(@"%@",error);
    }];
    
    //3.返回
    return _persistentContainer;
}

#pragma mark -iOS9 CoreData Stack
//返回沙盒的URL路径
- (NSURL *)getDocumentUrl
{
    return [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].firstObject;
}

//懒加载NSManagedObjectContext
- (NSManagedObjectContext *)managedObjectContext1
{
    if (_managedObjectContext1 != nil) {
        return _managedObjectContext1;
    }
    
    //1.创建管理对象上下文  参数是:指定上下文工作的队列环境   NSMainQueueConcurrencyType:在主线程中操作数据库  存储数据没有延迟NSPrivateQueueConcurrencyType:在子线程中操作数据库  存储数据有延迟
    _managedObjectContext1 = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    
    //2.设置存储调度器(因为存储数据的时候是管理上下文给存储调度器发指令)
    [_managedObjectContext1 setPersistentStoreCoordinator:self.persistentStoreCoordinator];
    
    //2.返回管理对象上下文
    return _managedObjectContext1;
}

//懒加载NSPersistentStoreCoordinator
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }
    //1.创建存储调度器  参数是:管理对象模型
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel];
    //2.添加存储器(存储调度器的职责是调度存储器,可以调度多个存储器)
    /**
     * 第一个参数type:存储类型  一般开发使用数据库形式存储
     * 第二个参数:configuration 存储配置 一般为nil 系统默认
     * 第二个参数:URL :数据库的文件URL路径
     * 第三个参数:options 属性设置  一般为nil 系统默认
     * 第四个参数:error
     */
    
    //拼接存储文件的URL路径(数据库文件后缀一般为sqlite 或者db  乱写的话用数据库软件就会打不开)
    NSURL *url = [[self getDocumentUrl] URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.db",kFileName] isDirectory:YES];
    [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:nil];
    //3.返回存储调度器
    return _persistentStoreCoordinator;
}

//懒加载NSManagedObjectModel
- (NSManagedObjectModel *)managedObjectModel
{
    if (_managedObjectModel != nil) {
        return _managedObjectModel;
    }
    
    //1.创建管理对象模型  参数:.xcdatamodeld文件的bunlde路径  代码中模型文件的后缀名只能用:momd  如果用:xcdatamodeld则会崩溃报错CoreData: Cannot load NSManagedObjectModel.  nil is an illegal URL parameter
    
    //该方法只能表示一个模型文件,如果应用程序中添加了多个模型文件,则无法储存数据
    //    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"Model" withExtension:@"momd"]];
    
    
    //1.使用文件合并的方式创建管理对象的模型  参数:模型文件bundle路径的集合   如果给的是nil 则表示会自动合并mainbundle中的所有的模型文件
    _managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
    
    //2.返回管理对象模型
    return _managedObjectModel;
}

- (void)save
{
    [self.managedObjectContext save:nil];
}

- (void)deleteAllEntities
{
    
    
//兼容所有iOS版本

        //1.获取数据库文件路径
        NSString *path1 = [[[self getDocumentUrl] path] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.db",kFileName]];
        NSString *path2 = [[[self getDocumentUrl] path] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.db-shm",kFileName]];
        NSString *path3 = [[[self getDocumentUrl] path] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.db-wal",kFileName]];
        //2.删除文件
        NSError *error = nil;
        [[NSFileManager defaultManager] removeItemAtPath:path1 error:&error];
        [[NSFileManager defaultManager] removeItemAtPath:path2 error:&error];
        [[NSFileManager defaultManager] removeItemAtPath:path3 error:&error];
        
        if (error == nil) {
            NSLog(@"清除数据库成功");
        }
        else
        {
            NSLog(@"清除数据库失败:%@",error.description);
        }
        
        
        //移除旧的存储器  (上一次的数据保留在存储的缓存中)
        [kHMCoreDataManager.managedObjectContext.persistentStoreCoordinator removePersistentStore:kHMCoreDataManager.managedObjectContext.persistentStoreCoordinator.persistentStores[0] error:nil];
        
        //添加新的存储器
        NSURL *url = [[self getDocumentUrl] URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.db",kFileName] isDirectory:YES];
        [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:nil];
    
}


@end
